home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Tools / Win95 Secrets / SETUP.Z / COMMON.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  23.6 KB  |  693 lines

  1. //==================================
  2. // PEDUMP - Matt Pietrek 1995
  3. // FILE: COMMON.C
  4. //==================================
  5.  
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include "common.h"
  11.  
  12. PIMAGE_SYMBOL PCOFFSymbolTable = 0; // RVA to COFF symbol table (if present)
  13. DWORD COFFSymbolCount = 0;          // Number of symbols in COFF symbol table
  14.  
  15. typedef struct
  16. {
  17.     WORD    flag;
  18.     PSTR    name;
  19. } WORD_FLAG_DESCRIPTIONS;
  20.  
  21. typedef struct
  22. {
  23.     DWORD   flag;
  24.     PSTR    name;
  25. } DWORD_FLAG_DESCRIPTIONS;
  26.  
  27. // Bitfield values and names for the IMAGE_FILE_HEADER flags
  28. WORD_FLAG_DESCRIPTIONS ImageFileHeaderCharacteristics[] = 
  29. {
  30. { IMAGE_FILE_RELOCS_STRIPPED, "RELOCS_STRIPPED" },
  31. { IMAGE_FILE_EXECUTABLE_IMAGE, "EXECUTABLE_IMAGE" },
  32. { IMAGE_FILE_LINE_NUMS_STRIPPED, "LINE_NUMS_STRIPPED" },
  33. { IMAGE_FILE_LOCAL_SYMS_STRIPPED, "LOCAL_SYMS_STRIPPED" },
  34. // { IMAGE_FILE_MINIMAL_OBJECT, "MINIMAL_OBJECT" }, // Removed in NT 3.5
  35. // { IMAGE_FILE_UPDATE_OBJECT, "UPDATE_OBJECT" },   // Removed in NT 3.5
  36. // { IMAGE_FILE_16BIT_MACHINE, "16BIT_MACHINE" },   // Removed in NT 3.5
  37. { IMAGE_FILE_BYTES_REVERSED_LO, "BYTES_REVERSED_LO" },
  38. { IMAGE_FILE_32BIT_MACHINE, "32BIT_MACHINE" },
  39. { IMAGE_FILE_DEBUG_STRIPPED, "DEBUG_STRIPPED" },
  40. // { IMAGE_FILE_PATCH, "PATCH" },
  41. { IMAGE_FILE_SYSTEM, "SYSTEM" },
  42. { IMAGE_FILE_DLL, "DLL" },
  43. { IMAGE_FILE_BYTES_REVERSED_HI, "BYTES_REVERSED_HI" }
  44. };
  45.  
  46. #define NUMBER_IMAGE_HEADER_FLAGS \
  47.     (sizeof(ImageFileHeaderCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS))
  48.  
  49. //
  50. // Dump the IMAGE_FILE_HEADER for a PE file or an OBJ
  51. //
  52. void DumpHeader(PIMAGE_FILE_HEADER pImageFileHeader)
  53. {
  54.     UINT headerFieldWidth = 30;
  55.     UINT i;
  56.     char *szMachine;
  57.     
  58.     printf("File Header\n");
  59.  
  60.     switch( pImageFileHeader->Machine )
  61.     {
  62.         case IMAGE_FILE_MACHINE_I386:   szMachine = "i386"; break;
  63.         // case IMAGE_FILE_MACHINE_I860:    szMachine = "i860"; break;
  64.         case IMAGE_FILE_MACHINE_R3000:  szMachine = "R3000"; break;
  65.         case IMAGE_FILE_MACHINE_R4000:  szMachine = "R4000"; break;
  66.         case IMAGE_FILE_MACHINE_ALPHA:  szMachine = "alpha"; break;
  67.         default:    szMachine = "unknown"; break;
  68.     }
  69.  
  70.     printf("  %-*s%04X (%s)\n", headerFieldWidth, "Machine:", 
  71.                 pImageFileHeader->Machine, szMachine);
  72.     printf("  %-*s%04X\n", headerFieldWidth, "Number of Sections:",
  73.                 pImageFileHeader->NumberOfSections);
  74.     printf("  %-*s%08X\n", headerFieldWidth, "TimeDateStamp:",
  75.                 pImageFileHeader->TimeDateStamp);
  76.     printf("  %-*s%08X\n", headerFieldWidth, "PointerToSymbolTable:",
  77.                 pImageFileHeader->PointerToSymbolTable);
  78.     printf("  %-*s%08X\n", headerFieldWidth, "NumberOfSymbols:",
  79.                 pImageFileHeader->NumberOfSymbols);
  80.     printf("  %-*s%04X\n", headerFieldWidth, "SizeOfOptionalHeader:",
  81.                 pImageFileHeader->SizeOfOptionalHeader);
  82.     printf("  %-*s%04X\n", headerFieldWidth, "Characteristics:",
  83.                 pImageFileHeader->Characteristics);
  84.     for ( i=0; i < NUMBER_IMAGE_HEADER_FLAGS; i++ )
  85.     {
  86.         if ( pImageFileHeader->Characteristics & 
  87.              ImageFileHeaderCharacteristics[i].flag )
  88.             printf( "    %s\n", ImageFileHeaderCharacteristics[i].name );
  89.     }
  90. }
  91.  
  92. #if 0
  93. // Marked as obsolete in MSDN CD 9
  94. // Bitfield values and names for the DllCharacteritics flags
  95. WORD_FLAG_DESCRIPTIONS DllCharacteristics[] = 
  96. {
  97. { IMAGE_LIBRARY_PROCESS_INIT, "PROCESS_INIT" },
  98. { IMAGE_LIBRARY_PROCESS_TERM, "PROCESS_TERM" },
  99. { IMAGE_LIBRARY_THREAD_INIT, "THREAD_INIT" },
  100. { IMAGE_LIBRARY_THREAD_TERM, "THREAD_TERM" },
  101. };
  102. #define NUMBER_DLL_CHARACTERISTICS \
  103.     (sizeof(DllCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS))
  104. #endif
  105.  
  106. #if 0
  107. // Marked as obsolete in MSDN CD 9
  108. // Bitfield values and names for the LoaderFlags flags
  109. DWORD_FLAG_DESCRIPTIONS LoaderFlags[] = 
  110. {
  111. { IMAGE_LOADER_FLAGS_BREAK_ON_LOAD, "BREAK_ON_LOAD" },
  112. { IMAGE_LOADER_FLAGS_DEBUG_ON_LOAD, "DEBUG_ON_LOAD" }
  113. };
  114. #define NUMBER_LOADER_FLAGS \
  115.     (sizeof(LoaderFlags) / sizeof(DWORD_FLAG_DESCRIPTIONS))
  116. #endif
  117.  
  118. // Names of the data directory elements that are defined
  119. char *ImageDirectoryNames[] = {
  120.     "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC",
  121.     "DEBUG", "COPYRIGHT", "GLOBALPTR", "TLS", "LOAD_CONFIG",
  122.     "BOUND_IMPORT", "IAT" };    // These last two entries added for NT 3.51
  123.  
  124. #define NUMBER_IMAGE_DIRECTORY_ENTRYS \
  125.     (sizeof(ImageDirectoryNames)/sizeof(char *))
  126.  
  127. //
  128. // Dump the IMAGE_OPTIONAL_HEADER from a PE file
  129. //
  130. void DumpOptionalHeader(PIMAGE_OPTIONAL_HEADER optionalHeader)
  131. {
  132.     UINT width = 30;
  133.     char *s;
  134.     UINT i;
  135.     
  136.     printf("Optional Header\n");
  137.     
  138.     printf("  %-*s%04X\n", width, "Magic", optionalHeader->Magic);
  139.     printf("  %-*s%u.%02u\n", width, "linker version",
  140.         optionalHeader->MajorLinkerVersion,
  141.         optionalHeader->MinorLinkerVersion);
  142.     printf("  %-*s%X\n", width, "size of code", optionalHeader->SizeOfCode);
  143.     printf("  %-*s%X\n", width, "size of initialized data",
  144.         optionalHeader->SizeOfInitializedData);
  145.     printf("  %-*s%X\n", width, "size of uninitialized data",
  146.         optionalHeader->SizeOfUninitializedData);
  147.     printf("  %-*s%X\n", width, "entrypoint RVA",
  148.         optionalHeader->AddressOfEntryPoint);
  149.     printf("  %-*s%X\n", width, "base of code", optionalHeader->BaseOfCode);
  150.     printf("  %-*s%X\n", width, "base of data", optionalHeader->BaseOfData);
  151.     printf("  %-*s%X\n", width, "image base", optionalHeader->ImageBase);
  152.  
  153.     printf("  %-*s%X\n", width, "section align",
  154.         optionalHeader->SectionAlignment);
  155.     printf("  %-*s%X\n", width, "file align", optionalHeader->FileAlignment);
  156.     printf("  %-*s%u.%02u\n", width, "required OS version",
  157.         optionalHeader->MajorOperatingSystemVersion,
  158.         optionalHeader->MinorOperatingSystemVersion);
  159.     printf("  %-*s%u.%02u\n", width, "image version",
  160.         optionalHeader->MajorImageVersion,
  161.         optionalHeader->MinorImageVersion);
  162.     printf("  %-*s%u.%02u\n", width, "subsystem version",
  163.         optionalHeader->MajorSubsystemVersion,
  164.         optionalHeader->MinorSubsystemVersion);
  165.     printf("  %-*s%X\n", width, "Reserved1", optionalHeader->Reserved1);
  166.     printf("  %-*s%X\n", width, "size of image", optionalHeader->SizeOfImage);
  167.     printf("  %-*s%X\n", width, "size of headers",
  168.             optionalHeader->SizeOfHeaders);
  169.     printf("  %-*s%X\n", width, "checksum", optionalHeader->CheckSum);
  170.     switch( optionalHeader->Subsystem )
  171.     {
  172.         case IMAGE_SUBSYSTEM_NATIVE: s = "Native"; break;
  173.         case IMAGE_SUBSYSTEM_WINDOWS_GUI: s = "Windows GUI"; break;
  174.         case IMAGE_SUBSYSTEM_WINDOWS_CUI: s = "Windows character"; break;
  175.         case IMAGE_SUBSYSTEM_OS2_CUI: s = "OS/2 character"; break;
  176.         case IMAGE_SUBSYSTEM_POSIX_CUI: s = "Posix character"; break;
  177.         default: s = "unknown";
  178.     }
  179.     printf("  %-*s%04X (%s)\n", width, "Subsystem",
  180.             optionalHeader->Subsystem, s);
  181.  
  182. #if 0
  183. // Marked as obsolete in MSDN CD 9
  184.     printf("  %-*s%04X\n", width, "DLL flags",
  185.             optionalHeader->DllCharacteristics);
  186.     for ( i=0; i < NUMBER_DLL_CHARACTERISTICS; i++ )
  187.     {
  188.         if ( optionalHeader->DllCharacteristics & 
  189.              DllCharacteristics[i].flag )
  190.             printf( "  %s", DllCharacteristics[i].name );
  191.     }
  192.     if ( optionalHeader->DllCharacteristics )
  193.         printf("\n");
  194. #endif
  195.  
  196.     printf("  %-*s%X\n", width, "stack reserve size",
  197.         optionalHeader->SizeOfStackReserve);
  198.     printf("  %-*s%X\n", width, "stack commit size",
  199.         optionalHeader->SizeOfStackCommit);
  200.     printf("  %-*s%X\n", width, "heap reserve size",
  201.         optionalHeader->SizeOfHeapReserve);
  202.     printf("  %-*s%X\n", width, "heap commit size",
  203.         optionalHeader->SizeOfHeapCommit);
  204.  
  205. #if 0
  206. // Marked as obsolete in MSDN CD 9
  207.     printf("  %-*s%08X\n", width, "loader flags",
  208.         optionalHeader->LoaderFlags);
  209.  
  210.     for ( i=0; i < NUMBER_LOADER_FLAGS; i++ )
  211.     {
  212.         if ( optionalHeader->LoaderFlags & 
  213.              LoaderFlags[i].flag )
  214.             printf( "  %s", LoaderFlags[i].name );
  215.     }
  216.     if ( optionalHeader->LoaderFlags )
  217.         printf("\n");
  218. #endif
  219.  
  220.     printf("  %-*s%X\n", width, "RVAs & sizes",
  221.         optionalHeader->NumberOfRvaAndSizes);
  222.  
  223.     printf("\nData Directory\n");
  224.     for ( i=0; i < optionalHeader->NumberOfRvaAndSizes; i++)
  225.     {
  226.         printf( "  %-12s rva: %08X  size: %08X\n",
  227.             (i >= NUMBER_IMAGE_DIRECTORY_ENTRYS)
  228.                 ? "unused" : ImageDirectoryNames[i], 
  229.             optionalHeader->DataDirectory[i].VirtualAddress,
  230.             optionalHeader->DataDirectory[i].Size);
  231.     }
  232. }
  233.  
  234. // Bitfield values and names for the IMAGE_SECTION_HEADER flags
  235. DWORD_FLAG_DESCRIPTIONS SectionCharacteristics[] = 
  236. {
  237. { IMAGE_SCN_CNT_CODE, "CODE" },
  238. { IMAGE_SCN_CNT_INITIALIZED_DATA, "INITIALIZED_DATA" },
  239. { IMAGE_SCN_CNT_UNINITIALIZED_DATA, "UNINITIALIZED_DATA" },
  240. { IMAGE_SCN_LNK_INFO, "LNK_INFO" },
  241. // { IMAGE_SCN_LNK_OVERLAY, "LNK_OVERLAY" },
  242. { IMAGE_SCN_LNK_REMOVE, "LNK_REMOVE" },
  243. { IMAGE_SCN_LNK_COMDAT, "LNK_COMDAT" },
  244. { IMAGE_SCN_MEM_DISCARDABLE, "MEM_DISCARDABLE" },
  245. { IMAGE_SCN_MEM_NOT_CACHED, "MEM_NOT_CACHED" },
  246. { IMAGE_SCN_MEM_NOT_PAGED, "MEM_NOT_PAGED" },
  247. { IMAGE_SCN_MEM_SHARED, "MEM_SHARED" },
  248. { IMAGE_SCN_MEM_EXECUTE, "MEM_EXECUTE" },
  249. { IMAGE_SCN_MEM_READ, "MEM_READ" },
  250. { IMAGE_SCN_MEM_WRITE, "MEM_WRITE" },
  251. };
  252.  
  253. #define NUMBER_SECTION_CHARACTERISTICS \
  254.     (sizeof(SectionCharacteristics) / sizeof(DWORD_FLAG_DESCRIPTIONS))
  255.  
  256. //
  257. // Dump the section table from a PE file or an OBJ
  258. //
  259. void DumpSectionTable(PIMAGE_SECTION_HEADER section,
  260.                       unsigned cSections,
  261.                       BOOL IsEXE)
  262. {
  263.     unsigned i, j;
  264.  
  265.     printf("Section Table\n");
  266.     
  267.     for ( i=1; i <= cSections; i++, section++ )
  268.     {
  269.         printf( "  %02X %-8.8s  %s: %08X  VirtAddr:  %08X\n",
  270.                 i, section->Name,
  271.                 IsEXE ? "VirtSize" : "PhysAddr",
  272.                 section->Misc.VirtualSize, section->VirtualAddress);
  273.         printf( "    raw data offs:   %08X  raw data size: %08X\n",
  274.                 section->PointerToRawData, section->SizeOfRawData );
  275.         printf( "    relocation offs: %08X  relocations:   %08X\n",
  276.                 section->PointerToRelocations, section->NumberOfRelocations );
  277.         printf( "    line # offs:     %08X  line #'s:      %08X\n",
  278.                 section->PointerToLinenumbers, section->NumberOfLinenumbers );
  279.         printf( "    characteristics: %08X\n", section->Characteristics);
  280.  
  281.         printf("    ");
  282.         for ( j=0; j < NUMBER_SECTION_CHARACTERISTICS; j++ )
  283.         {
  284.             if ( section->Characteristics & 
  285.                 SectionCharacteristics[j].flag )
  286.                 printf( "  %s", SectionCharacteristics[j].name );
  287.         }
  288.         printf("\n\n");
  289.     }
  290. }
  291.  
  292. //
  293. // Used by the DumpSymbolTable() routine.  It purpose is to filter out
  294. // the non-normal section numbers and give them meaningful names.
  295. //
  296. void GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
  297. {
  298.     char tempbuffer[10];
  299.     
  300.     switch ( (SHORT)section )
  301.     {
  302.         case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
  303.         case IMAGE_SYM_ABSOLUTE:  strcpy(tempbuffer, "ABS  "); break;
  304.         case IMAGE_SYM_DEBUG:     strcpy(tempbuffer, "DEBUG"); break;
  305.         default: sprintf(tempbuffer, "%-5X", section);
  306.     }
  307.     
  308.     strncpy(buffer, tempbuffer, cbBuffer-1);
  309. }
  310.  
  311. // The names of the first group of possible symbol table storage classes
  312. char * SzStorageClass1[] = {
  313. "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
  314. "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
  315. "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
  316. "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
  317. };
  318.  
  319. // The names of the second group of possible symbol table storage classes
  320. char * SzStorageClass2[] = {
  321. "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
  322. };
  323.  
  324. //
  325. // Given a symbol storage class value, return a descriptive ASCII string
  326. //
  327. PSTR GetSZStorageClass(BYTE storageClass)
  328. {
  329.     if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
  330.         return SzStorageClass1[storageClass];
  331.     else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
  332.               && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
  333.         return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
  334.     else
  335.         return "???";
  336. }
  337.  
  338. //
  339. // Dumps the auxillary symbol for a regular symbol.  It takes a pointer
  340. // to the regular symbol, since the routine needs the information in
  341. // that record.
  342. //
  343. void DumpAuxSymbols(PIMAGE_SYMBOL pSymbolTable)
  344. {
  345.     PIMAGE_AUX_SYMBOL auxSym;
  346.     
  347.     auxSym = (PIMAGE_AUX_SYMBOL)(pSymbolTable+1);
  348.     
  349.     if ( pSymbolTable->StorageClass == IMAGE_SYM_CLASS_FILE )
  350.         printf("     * %s\n", auxSym);
  351.     else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) )
  352.     {
  353.         if ( (pSymbolTable->Type & 0xF0) == (IMAGE_SYM_DTYPE_FUNCTION << 4))
  354.         {   
  355.         printf("     * tag: %04X  size: %04X  Line #'s: %08X  next fn: %04X\n",
  356.             auxSym->Sym.TagIndex, auxSym->Sym.Misc.TotalSize,
  357.             auxSym->Sym.FcnAry.Function.PointerToLinenumber,
  358.             auxSym->Sym.FcnAry.Function.PointerToNextFunction);
  359.         }
  360.     }
  361.     else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_STATIC) )
  362.     {
  363.         printf(
  364.             "     * Section: %04X  Len: %05X  Relocs: %04X  LineNums: %04X\n",
  365.             auxSym->Section.Number, auxSym->Section.Length,
  366.             auxSym->Section.NumberOfRelocations,
  367.             auxSym->Section.NumberOfLinenumbers);
  368.     }
  369. }
  370.  
  371. //
  372. // Given a COFF symbol table index, look up its name.  This function assumes
  373. // that the COFFSymbolCount and PCOFFSymbolTable variables have been already
  374. // set up.
  375. //
  376. BOOL LookupSymbolName(DWORD index, PSTR buffer, UINT length)
  377. {
  378.     PSTR stringTable;
  379.  
  380.     if ( index >= COFFSymbolCount )
  381.         return FALSE;
  382.     
  383.     if ( PCOFFSymbolTable == 0 )
  384.         return FALSE;
  385.     
  386.     if ( PCOFFSymbolTable[index].N.Name.Short != 0 )
  387.     {
  388.         strncpy(buffer, PCOFFSymbolTable[index].N.ShortName, min(8,length));
  389.         buffer[8] = 0;
  390.     }
  391.     else
  392.     {
  393.         stringTable = (PSTR)&PCOFFSymbolTable[COFFSymbolCount]; 
  394.         strncpy(buffer,
  395.                 stringTable + PCOFFSymbolTable[index].N.Name.Long, length);
  396.         buffer[length-1] = 0;
  397.     }
  398.     
  399.     return TRUE;
  400. }
  401.  
  402. //
  403. // Dumps a COFF symbol table from an EXE or OBJ
  404. //
  405. void DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, unsigned cSymbols)
  406. {
  407.     unsigned i;
  408.     PSTR stringTable;
  409.     char sectionName[10];
  410.     
  411.     printf("Symbol Table - %X entries  (* = auxillary symbol)\n", cSymbols);
  412.  
  413.     printf(
  414.     "Indx Name                 Value    Section    cAux  Type    Storage\n"
  415.     "---- -------------------- -------- ---------- ----- ------- --------\n");
  416.  
  417.     // The string table apparently starts right after the symbol table
  418.     stringTable = (PSTR)&pSymbolTable[cSymbols]; 
  419.         
  420.     for ( i=0; i < cSymbols; i++ )
  421.     {
  422.         printf("%04X ", i);
  423.         
  424.         if ( pSymbolTable->N.Name.Short != 0 )
  425.             printf("%-20.8s", pSymbolTable->N.ShortName);
  426.         else
  427.             printf("%-20s", stringTable + pSymbolTable->N.Name.Long);
  428.         
  429.         printf(" %08X", pSymbolTable->Value);
  430.     
  431.         GetSectionName(pSymbolTable->SectionNumber, sectionName,
  432.                         sizeof(sectionName));
  433.         printf(" sect:%s aux:%X type:%02X st:%s\n",
  434.                 sectionName,
  435.                 pSymbolTable->NumberOfAuxSymbols,
  436.                 pSymbolTable->Type,
  437.                 GetSZStorageClass(pSymbolTable->StorageClass) );
  438.         
  439.         if ( pSymbolTable->NumberOfAuxSymbols )
  440.             DumpAuxSymbols(pSymbolTable);
  441.  
  442.         // Take into account any aux symbols
  443.         i += pSymbolTable->NumberOfAuxSymbols;
  444.         pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
  445.         pSymbolTable++;
  446.     }
  447. }
  448.  
  449. //
  450. // Given a section name, look it up in the section table and return a
  451. // pointer to the start of its raw data area.
  452. //
  453. LPVOID GetSectionPtr(PSTR name, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase)
  454. {
  455.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  456.     unsigned i;
  457.     
  458.     for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  459.     {
  460.         if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 )
  461.             return (LPVOID)(section->PointerToRawData + imageBase);
  462.     }
  463.     
  464.     return 0;
  465. }
  466.  
  467. //
  468. // Given a section name, look it up in the section table and return a
  469. // pointer to its IMAGE_SECTION_HEADER
  470. //
  471. PIMAGE_SECTION_HEADER GetSectionHeader(PSTR name, PIMAGE_NT_HEADERS pNTHeader)
  472. {
  473.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  474.     unsigned i;
  475.     
  476.     for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  477.     {
  478.         if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 )
  479.             return section;
  480.     }
  481.     
  482.     return 0;
  483. }
  484.  
  485. //
  486. // Given an RVA, look up the section header that encloses it and return a
  487. // pointer to its IMAGE_SECTION_HEADER
  488. //
  489. PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
  490.                                                 PIMAGE_NT_HEADERS pNTHeader)
  491. {
  492.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  493.     unsigned i;
  494.     
  495.     for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  496.     {
  497.         // Is the RVA within this section?
  498.         if ( (rva >= section->VirtualAddress) && 
  499.              (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
  500.             return section;
  501.     }
  502.     
  503.     return 0;
  504. }
  505.  
  506. //
  507. // Do a hexadecimal dump of the raw data for all the sections.  You
  508. // could just dump one section by adjusting the PIMAGE_SECTION_HEADER
  509. // and cSections parameters
  510. //
  511. void DumpRawSectionData(PIMAGE_SECTION_HEADER section,
  512.                         PVOID base,
  513.                         unsigned cSections)
  514. {
  515.     unsigned i;
  516.     char name[IMAGE_SIZEOF_SHORT_NAME + 1];
  517.  
  518.     printf("Section Hex Dumps\n");
  519.     
  520.     for ( i=1; i <= cSections; i++, section++ )
  521.     {
  522.         // Make a copy of the section name so that we can ensure that
  523.         // it's null-terminated
  524.         memcpy(name, section->Name, IMAGE_SIZEOF_SHORT_NAME);
  525.         name[IMAGE_SIZEOF_SHORT_NAME] = 0;
  526.  
  527.         // Don't dump sections that don't exist in the file!
  528.         if ( section->PointerToRawData == 0 )
  529.             continue;
  530.         
  531.         printf( "section %02X (%s)  size: %08X  file offs: %08X\n",
  532.                 i, name, section->SizeOfRawData, section->PointerToRawData);
  533.  
  534.         HexDump( MakePtr(PBYTE, base, section->PointerToRawData),
  535.                  section->SizeOfRawData );
  536.         printf("\n");
  537.     }
  538. }
  539.  
  540. //
  541. // Dump a range of line numbers from the COFF debug information
  542. //
  543. void DumpLineNumbers(PIMAGE_LINENUMBER pln, DWORD count)
  544. {
  545.     char buffer[64];
  546.     DWORD i;
  547.     
  548.     printf("Line Numbers\n");
  549.     
  550.     for (i=0; i < count; i++)
  551.     {
  552.         if ( pln->Linenumber == 0 ) // A symbol table index
  553.         {
  554.             buffer[0] = 0;
  555.             LookupSymbolName(pln->Type.SymbolTableIndex, buffer,
  556.                             sizeof(buffer));
  557.             printf("SymIndex: %X (%s)\n", pln->Type.SymbolTableIndex,
  558.                                              buffer);
  559.         }
  560.         else        // A regular line number
  561.             printf(" Addr: %05X  Line: %04X\n",
  562.                 pln->Type.VirtualAddress, pln->Linenumber);
  563.         pln++;
  564.     }
  565. }
  566.  
  567. PIMAGE_COFF_SYMBOLS_HEADER PCOFFDebugInfo = 0;
  568.  
  569. char *SzDebugFormats[] = {
  570. "UNKNOWN/BORLAND","COFF","CODEVIEW","FPO","MISC","EXCEPTION","FIXUP" };
  571.  
  572. //
  573. // Dump the debug directory array
  574. //
  575. void DumpDebugDirectory(PIMAGE_DEBUG_DIRECTORY debugDir, DWORD size, DWORD base)
  576. {
  577.     DWORD cDebugFormats = size / sizeof(IMAGE_DEBUG_DIRECTORY);
  578.     PSTR szDebugFormat;
  579.     unsigned i;
  580.     
  581.     if ( cDebugFormats == 0 )
  582.         return;
  583.     
  584.     printf(
  585.     "Debug Formats in File\n"
  586.     "  Type            Size     Address  FilePtr  Charactr TimeData Version\n"
  587.     "  --------------- -------- -------- -------- -------- -------- --------\n"
  588.     );
  589.     
  590.     for ( i=0; i < cDebugFormats; i++ )
  591.     {
  592.         szDebugFormat = (debugDir->Type <= 6)
  593.                         ? SzDebugFormats[debugDir->Type] : "???";
  594.  
  595.         printf("  %-15s %08X %08X %08X %08X %08X %u.%02u\n",
  596.             szDebugFormat, debugDir->SizeOfData, debugDir->AddressOfRawData,
  597.             debugDir->PointerToRawData, debugDir->Characteristics,
  598.             debugDir->TimeDateStamp, debugDir->MajorVersion,
  599.             debugDir->MinorVersion);
  600.  
  601.         // If COFF debug info, save its address away for later.  We
  602.         // do the check for "PointerToSymbolTable" because some files
  603.         // have bogus values for the COFF header offset.
  604.         if ( debugDir->Type == IMAGE_DEBUG_TYPE_COFF )
  605.         {
  606.             PCOFFDebugInfo =
  607.                 (PIMAGE_COFF_SYMBOLS_HEADER)(base+ debugDir->PointerToRawData);
  608.         }
  609.         
  610.         debugDir++;
  611.     }
  612. }
  613.  
  614. //
  615. // Dump the COFF debug information header
  616. //
  617. void DumpCOFFHeader(PIMAGE_COFF_SYMBOLS_HEADER pDbgInfo)
  618. {
  619.     printf("COFF Debug Info Header\n");
  620.     printf("  NumberOfSymbols:      %08X\n", pDbgInfo->NumberOfSymbols);
  621.     printf("  LvaToFirstSymbol:     %08X\n", pDbgInfo->LvaToFirstSymbol);
  622.     printf("  NumberOfLinenumbers:  %08X\n", pDbgInfo->NumberOfLinenumbers);
  623.     printf("  LvaToFirstLinenumber: %08X\n", pDbgInfo->LvaToFirstLinenumber);
  624.     printf("  RvaToFirstByteOfCode: %08X\n", pDbgInfo->RvaToFirstByteOfCode);
  625.     printf("  RvaToLastByteOfCode:  %08X\n", pDbgInfo->RvaToLastByteOfCode);
  626.     printf("  RvaToFirstByteOfData: %08X\n", pDbgInfo->RvaToFirstByteOfData);
  627.     printf("  RvaToLastByteOfData:  %08X\n", pDbgInfo->RvaToLastByteOfData);
  628. }
  629.  
  630.  
  631. // Number of hex values displayed per line
  632. #define HEX_DUMP_WIDTH 16
  633.  
  634. //
  635. // Dump a region of memory in a hexadecimal format
  636. //
  637. void HexDump(PBYTE ptr, DWORD length)
  638. {
  639.     char buffer[256];
  640.     PSTR buffPtr, buffPtr2;
  641.     unsigned cOutput, i;
  642.     DWORD bytesToGo=length;
  643.  
  644.     while ( bytesToGo  )
  645.     {
  646.         cOutput = bytesToGo >= HEX_DUMP_WIDTH ? HEX_DUMP_WIDTH : bytesToGo;
  647.  
  648.         buffPtr = buffer;
  649.         buffPtr += sprintf(buffPtr, "%08X:  ", length-bytesToGo );
  650.         buffPtr2 = buffPtr + (HEX_DUMP_WIDTH * 3) + 1;
  651.         
  652.         for ( i=0; i < HEX_DUMP_WIDTH; i++ )
  653.         {
  654.             BYTE value = *(ptr+i);
  655.  
  656.             if ( i >= cOutput )
  657.             {
  658.                 // On last line.  Pad with spaces
  659.                 *buffPtr++ = ' ';
  660.                 *buffPtr++ = ' ';
  661.                 *buffPtr++ = ' ';
  662.             }
  663.             else
  664.             {
  665.                 if ( value < 0x10 )
  666.                 {
  667.                     *buffPtr++ = '0';
  668.                     itoa( value, buffPtr++, 16);
  669.                 }
  670.                 else
  671.                 {
  672.                     itoa( value, buffPtr, 16);
  673.                     buffPtr+=2;
  674.                 }
  675.  
  676.                 *buffPtr++ = ' ';
  677.                 *buffPtr2++ = isprint(value) ? value : '.';
  678.             }
  679.             
  680.             // Put an extra space between the 1st and 2nd half of the bytes
  681.             // on each line.
  682.             if ( i == (HEX_DUMP_WIDTH/2)-1 )
  683.                 *buffPtr++ = ' ';
  684.         }
  685.  
  686.         *buffPtr2 = 0;  // Null terminate it.
  687.         puts(buffer);   // Can't use printf(), since there may be a '%'
  688.                         // in the string.
  689.         bytesToGo -= cOutput;
  690.         ptr += HEX_DUMP_WIDTH;
  691.     }
  692. }
  693.